package bot

import (
	"encoding/json"
	"fmt"
	"gorm.io/gorm"
	"io/ioutil"
	"lidongyooo/search-bot/models"
	"lidongyooo/search-bot/pkg/config"
	"lidongyooo/search-bot/pkg/db"
	"lidongyooo/search-bot/pkg/proxy"
	"log"
	"net/http"
	"reflect"
	"strings"
	"time"
)

type Chat struct {
	Name     string     `json:"name"`
	Type     string     `json:"type"`
	ID       int        `json:"id"`
	Messages []*Message `json:"messages"`
}

type Message struct {
	ID     int    `json:"id"`
	Type   string `json:"type"`
	Date   string `json:"date"`
	SentAt models.LocalTime
	Text   interface{} `json:"text"`
	From   string      `json:"from,omitempty"`
	FromID string      `json:"from_id,omitempty"`
}

func FileHandler(ms *MyMessage) {
	if !strings.HasSuffix(ms.Document.FileName, ".json") {
		Bot.SendMessage(ms.Chat.ID, "必须是 json 格式文件")
		return
	}

	if ms.Document.FileSize > 10240*1024 {
		Bot.SendMessage(ms.Chat.ID, "文件大小不能超过 10.0 MB")
		return
	}

	url, err := Bot.GetFileDirectURL(ms.Document.FileID)
	if err != nil {
		log.Println(err.Error())
		return
	}

	bytes, err := downloadFile(url)
	if err != nil {
		log.Println(err.Error())
		return
	}

	chat := &Chat{}
	json.Unmarshal(bytes, &chat)
	err = chat.create()
	if err != nil {
		Bot.SendMessage(ms.Chat.ID, err.Error())
		return
	}

	var messages []models.Message
	counter := 0
	tableName := GetMessageTableName(chat.ID)
	db.MessageTableCreate(tableName)
	for i := 0; i < len(chat.Messages); i++ {
		if chat.Messages[i].Type != "message" {
			continue
		}

		chat.Messages[i].Text = TextFormat(chat.Messages[i].Text)
		if chat.Messages[i].Text == "" {
			continue
		}

		if time, err := time.ParseInLocation("2006-01-02T15:04:05", chat.Messages[i].Date, time.Local); err == nil {
			chat.Messages[i].SentAt = models.LocalTime{Time: time}
		} else {
			log.Println(err.Error())
			continue
		}

		messages = append(messages, models.Message{
			MessageId: chat.Messages[i].ID,
			Text:      chat.Messages[i].Text.(string),
			FromName:  chat.Messages[i].From,
			FromId:    chat.Messages[i].FromID,
			SentAt:    chat.Messages[i].SentAt,
			ChatId:    chat.ID,
		})

		counter++
		if counter >= 500 {
			chat.messagesCreate(&messages)
			messages = nil
			counter = 0
		}
	}
	if len(messages) > 0 {
		chat.messagesCreate(&messages)
	}

	Bot.SendMessage(ms.Chat.ID, "聊天记录导入成功，在群组中使用'"+config.Viper.GetString("MESSAGE.SEARCH")+": 关键字'")
}

func (c *Chat) create() error {
	chatModel := &models.Chat{}
	res := db.MySQL.Where("chat_id", c.ID).First(chatModel)

	chatModel.ChatId = c.ID
	chatModel.Type = c.Type
	chatModel.Name = c.Name

	if chatModel.Status == 1 {
		return fmt.Errorf("历史聊天记录已导入，请勿重复操作")
	}

	chatModel.Status = 1
	if res.Error == gorm.ErrRecordNotFound {
		db.MySQL.Create(chatModel)
	} else {
		db.MySQL.Model(chatModel).Updates(chatModel)
	}
	return nil
}

func (c *Chat) messagesCreate(messages *[]models.Message) {
	tableName := GetMessageTableName(c.ID)
	db.MySQL.Table(tableName).Create(messages)
}

func TextFormat(text interface{}) string {
	v := reflect.ValueOf(text)
	content := ""

	switch v.Kind() {
	case reflect.String:
		content = v.String()
	case reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			content += TextFormat(v.Index(i).Interface())
		}
		return content
	case reflect.Map:
		for _, key := range v.MapKeys() {
			if key.String() == "text" {
				content = v.MapIndex(key).Interface().(string)
			}
		}
	}

	return strings.TrimSpace(content)
}

func downloadFile(url string) ([]byte, error) {
	client := proxy.Client()
	res, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("bad status: %s", res.Status)
	}

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	return body, nil
}
